home *** CD-ROM | disk | FTP | other *** search
- // the implementation of segseg
- // Copyright (C) 1997 Kazutaka Hirata <khirata@jove.acs.unt.edu>
-
- #include "../common/base.h"
- #include "hesse.h"
- #include "seg.h"
- #include "xydbl.h"
-
- #include "segseg.h"
-
- bool is_parallel(const XY_DBL& v1, const XY_DBL& v2)
- {
- return v1.x() * v2.y() == v1.y() * v2.x();
- }
-
- double segseg_core(const SEGMENT& seg1, const SEGMENT& seg2)
- {
- double distance = get_distance(seg1.p1(), seg2.p1());
- distance = minimum(distance, get_distance(seg1.p1(), seg2.p2()));
- distance = minimum(distance, get_distance(seg1.p2(), seg2.p1()));
- distance = minimum(distance, get_distance(seg1.p2(), seg2.p2()));
- HESSE hesse_1_1(SEGMENT(seg1.p1() - seg2.p1(), seg1.p2() - seg2.p1()));
- HESSE hesse_1_2(SEGMENT(seg1.p1() - seg2.p2(), seg1.p2() - seg2.p2()));
- HESSE hesse_2_1(SEGMENT(seg2.p1() - seg1.p1(), seg2.p2() - seg1.p1()));
- HESSE hesse_2_2(SEGMENT(seg2.p1() - seg1.p2(), seg2.p2() - seg1.p2()));
- if(hesse_1_1.on_segment()
- || hesse_1_2.on_segment()
- || hesse_2_1.on_segment()
- || hesse_2_2.on_segment()) {
- if(hesse_1_1.on_segment()) {
- distance = minimum(distance, hesse_1_1.c());
- }
- if(hesse_1_2.on_segment()) {
- distance = minimum(distance, hesse_1_2.c());
- }
- if(hesse_2_1.on_segment()) {
- distance = minimum(distance, hesse_2_1.c());
- }
- if(hesse_2_2.on_segment()) {
- distance = minimum(distance, hesse_2_2.c());
- }
- } else {
- }
- return distance;
- }
-
- double segseg(const SEGMENT& seg1, const SEGMENT& seg2)
- {
- XY_DBL v1 = seg1.get_vector();
- XY_DBL v2 = seg2.get_vector();
-
- double distance;
- if(is_parallel(v1, v2)) {
- SEGMENT seg(seg1.p1(), seg2.p1());
- XY_DBL v = seg.get_vector();
- if(is_parallel(v, v1)) {
- if(seg1.is_vertical()) {
- double y1_max = maximum(seg1.p1().y(), seg1.p2().y());
- double y1_min = minimum(seg1.p1().y(), seg1.p2().y());
- double y2_max = maximum(seg2.p1().y(), seg2.p2().y());
- double y2_min = minimum(seg2.p1().y(), seg2.p2().y());
- if(y1_max < y2_min) {
- distance = y2_min - y1_max;
- } else if (y2_max < y1_min) {
- distance = y2_min - y1_max;
- } else {
- distance = 0;
- }
- } else {
- double x1_max = maximum(seg1.p1().x(), seg1.p2().x());
- double x1_min = minimum(seg1.p1().x(), seg1.p2().x());
- double x2_max = maximum(seg2.p1().x(), seg2.p2().x());
- double x2_min = minimum(seg2.p1().x(), seg2.p2().x());
- if(x1_max < x2_min) {
- double xdst = x2_min - x1_max;
- double ydst = xdst * v1.y() / v1.x();
- distance = sqrt(xdst * xdst + ydst * ydst);
- } else if (x2_max < x1_min) {
- double xdst = x2_min - x1_max;
- double ydst = xdst * v1.y() / v1.x();
- distance = sqrt(xdst * xdst + ydst * ydst);
- } else {
- distance = 0;
- }
- }
- } else {
- distance = segseg_core(seg1, seg2);
- }
- } else {
- double den = v1.y() * (seg2.p1().x() - seg1.p1().x())
- - v1.x() * (seg2.p1().y() - seg1.p1().y());
- double num = v1.x() * v2.y() - v1.y() * v2.x();
- double s = den / num;
- XY_DBL isec(
- v2.x() * s + seg2.p1().x(),
- v2.y() * s + seg2.p1().y()
- );
- bool on_segment1;
- if(seg1.is_vertical()) {
- on_segment1 = seg1.is_y_on_segment(isec.y());
- } else {
- on_segment1 = seg1.is_x_on_segment(isec.x());
- }
- bool on_segment2;
- if(seg2.is_vertical()) {
- on_segment2 = seg2.is_y_on_segment(isec.y());
- } else {
- on_segment2 = seg2.is_x_on_segment(isec.x());
- }
- if(on_segment1 && on_segment2) {
- distance = 0;
- } else {
- distance = segseg_core(seg1, seg2);
- }
- }
-
- return distance;
- }
-